package com.dyb.demo.innerClass;

public class Outer {
    private static int out_x = 1;

    /**
     * 在方法体中定义内部类
     */
    public void method() {
        int a = 0;
        Inner1 inner1 = new Inner1();

        // 定义在方法中的内部类，不能使用 访问类型修饰符，可以使用final、abstract修饰符
        abstract class Inner2 {
            public void method() {
                // 可以访问，但是不能修改
                // 在方法的内部类中，可以访问方法的非final字段，
                // 但是要保证在字段初始化后永远不在对其赋值，因为内部类访问方法字段时默认加final修饰
                // 如果初始化后再对方法内部类访问的字段赋值，将导致方法内部类访问字段失败
                // 一般建议将方法内部类访问的字段使用final修饰，防止再对其值进行修改
                out_x = a;
                // a = out_x;
            }
        }

        // Inner2必须在使用前定义
        class Inner3 extends Inner2 {

            @Override
            public void method() {
                super.method();
            }
        }

        new Inner3();
    }

    /**
     * 定义在static方法中定义内部类
     * 内部类访问方法的属性, 默认加final修饰，只能在初始化时赋值；
     * @param a
     */
    static void method(int a) {
        int i = 4;
        class Inner4 {
            public void method() {
                int s = i * a;
                // 不能再方法内部类中对方法的属性值进行修改
                //  i = i * a;
            }
        }
    }

    public void method(String string) {
        method(1);
    }

    /**
     * 定义在方法外部的内部了可以使用四种访问修饰符，public、protected、默认、private
     */
    public class Inner1 {
        public void method() {
            out_x = 0;
        }
    }

    /**
     * 静态内部类只能访问外部类的静态属性
     */
    public static class Inner4 {
        public void method() {
            out_x = 0;
        }
    }

}

class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        // 普通内部类需要先创建外部类实例
        Outer.Inner1 inner1 = outer.new Inner1();
        // 静态内部类直接new 外部类.内部类() 创建， 不需要创建外部类
        Outer.Inner4 inner4 = new Outer.Inner4();
    }

}